#ifndef __FACTORY_H__
#define __FACTORY_H__
#include <iostream>
#include <string>

class TwoNumberOperate{
protected:
    double m_numA;
    double m_numB;
public:
    virtual  ~TwoNumberOperate() =default;
    virtual int GetResult() = 0;
    void setNumberA(double a){
        m_numA = a;
    }
    void setNumberB(double b){
        m_numB = b;
    }
};

class TwoNumberAddOperate : public TwoNumberOperate{
public:
    virtual int GetResult(){
                  
        return m_numA + m_numB;
    }
};

class TwoNumberSubOperate: public TwoNumberOperate{
public:
    virtual int GetResult(){
        return m_numA - m_numB;
    }
};

class TwoNumberMultipleOperate: public TwoNumberOperate{
public:
    virtual int GetResult(){
        return m_numA * m_numB;
    }
};

class TwoNumberDivideOperate: public TwoNumberOperate{
public:
    virtual int GetResult(){
        if(m_numB == 0)
            throw std::bad_cast();
        return m_numA / m_numB;
    }
};

class TwoNumberResidualOperate: public TwoNumberOperate{
public:
    virtual int GetResult(){
        if(m_numB == 0)
            throw std::bad_cast();
        return int(m_numA) % int(m_numB);
    }
};

class Factory{
public:
    virtual ~Factory() = default;
    virtual TwoNumberOperate* CreateTwoNumberOperator() = 0;
};

class TwoNumberAddOperateFactory: public Factory{
public:
    virtual TwoNumberOperate* CreateTwoNumberOperator(){
        return new TwoNumberAddOperate();
    }
};

class TwoNumberSubOperateFactory: public Factory{
public:
    virtual TwoNumberOperate* CreateTwoNumberOperator(){
        return new TwoNumberSubOperate();
    }
};

class TwoNumberMultipleOperateFactory: public Factory{
public:
    virtual TwoNumberOperate* CreateTwoNumberOperator(){
        return new TwoNumberMultipleOperate();
    }
};

class TwoNumberDivideOperateFactory: public Factory{
public:
    virtual TwoNumberOperate* CreateTwoNumberOperator(){
        return new TwoNumberDivideOperate();
    }
};

class TwoNumberResidualOperateFactory: public Factory{
public:
    virtual TwoNumberOperate* CreateTwoNumberOperator(){
        return new TwoNumberResidualOperate();
    }
};

#endif